package com.jhgsys.internal.sypq.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jhgsys.internal.common.utils.DateUtil;
import com.jhgsys.internal.sypq.entity.Calendar;
import com.jhgsys.internal.sypq.entity.*;
import com.jhgsys.internal.sypq.mapper.TaskMapper;
import com.jhgsys.internal.sypq.service.*;
import com.jhgsys.internal.system.entity.User;
import com.jhgsys.internal.system.service.IUserService;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.jhgsys.internal.common.utils.FebsUtil.getCurrentUser;

/**
 * 任务管理 Service实现
 *
 * @author ganjun
 * @date 2024-11-18 10:06:38
 */
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class ScheduleServiceImpl extends ServiceImpl<TaskMapper, Task> implements IScheduleService {
    @Autowired
    IResourceService resourceService;
    @Autowired
    IWorkflowRecordService workflowRecordService;
    @Autowired
    ITaskShipService taskShipService;
    @Autowired
    ITaskOarsService taskOarsService;
    @Autowired
    ITaskAttachService taskAttachService;
    @Autowired
    ICalendarService calendarService;
    @Autowired
    IModelShipService modelShipService;
    @Autowired
    IModelOarsService modelOarsService;
    @Autowired
    IModelAttachService modelAttachService;
    @Autowired
    ITaskService taskService;

    @Autowired
    private INoticeService noticeService;

    @Autowired
    private IUserService userService;

    @Override
    public List<ScheduleDto> findTaskPage(TaskDto taskDto, boolean isAdmin) {
        List<TaskDto> list = getAssembledTask(taskDto);
        //筛选我的排期
        String currentUser = getCurrentUser().getUserId();
        if ("1".equals(taskDto.getMySchedule())) {
            list = list.stream().filter(obj -> {
                return Arrays.asList(obj.getManagerids().split(",")).contains(currentUser);
            }).collect(Collectors.toList());
        }

        Map<String, List<TaskDto>> map = list.stream().collect(Collectors.groupingBy(TaskDto::getRsid));
        List<ScheduleDto> scheduleDtoList = new ArrayList<>();
        //过滤权限
        for (String rsid : map.keySet()) {
            boolean hasAuth = false;
            ScheduleDto scheduleDto = new ScheduleDto();
            List<TaskDto> taskDtoList = map.get(rsid);
            if (taskDtoList == null || taskDtoList.isEmpty()) {
                Resource resource = this.resourceService.getById(rsid);
                if (resource != null) {
                    scheduleDto.setName(resource.getRsName());
                    scheduleDto.setRsName(resource.getRsName());
                    scheduleDto.setRsCode(resource.getRsNo());
                    scheduleDto.setId(resource.getRsNo());
                    if (currentUser.equals(resource.getRsDirector())) {
                        hasAuth = true;
                    }
                }
            } else {
                TaskDto obj = taskDtoList.get(0);
                scheduleDto.setName(obj.getRsName());
                scheduleDto.setRsName(obj.getRsName());
                scheduleDto.setRsCode(obj.getRsCode());
                scheduleDto.setId(obj.getRsCode());
                scheduleDto.setTaskList(taskDtoList);
                if (currentUser.equals(obj.getRsDirector())) {
                    hasAuth = true;
                }
                for (TaskDto dto : taskDtoList) {
                    boolean isPermitted = SecurityUtils.getSubject().isPermitted("schedule:edit");
                    //是项目经理或资源负责人.项目审批人并且具有修改权限，才能够拖动工期
                    dto.setIsDrag((StringUtils.isNotEmpty(dto.getManagerids()) && Arrays.asList(dto.getManagerids().split(",")).contains(currentUser)
                                   || currentUser.equals(dto.getRsDirector()) || currentUser.equals(dto.getAuditorid()) || isAdmin) && isPermitted);
                }
            }
            //资源主管或项目经理权限
            if (hasAuth || isAdmin || SecurityUtils.getSubject().hasRole("项目经理")) {
                scheduleDtoList.add(scheduleDto);
            }
        }
        return scheduleDtoList;
    }


    public void oneKeyAssemblie(TaskDto taskDto, boolean isAdmin) throws Exception {
        //未排期,计划开始时间和结束时间为空，并且任务类型为排期类型
        List<TaskDto> list = this.baseMapper.getSchedule(taskDto);
        String currentUser = getCurrentUser().getUserId();
        List<TaskDto> unScheduleList = list.stream().filter(obj -> {
            return (obj.getPlanStartdate() == null || obj.getPlanEnddate() == null)
                   && obj.getTaskType() == 1 && obj.getStatus() < 4 && obj.getTestDay() != null && obj.getRsid() != null;
        }).collect(Collectors.toList());

        //计算开始时间，从模型中实际完成时间和要求完成时间中取最大值,再加1天
        unScheduleList.forEach(obj -> calculateMinStartDate(obj));
        //已排期，并且结束时间天于当前时间
        List<TaskDto> scheduledList =
                list.stream().filter(obj -> obj.getPlanStartdate() != null && obj.getPlanEnddate() != null && obj.getRsid() != null
                                            && obj.getPlanEnddate().getTime() > (new Date()).getTime()).collect(Collectors.toList());
        calculateSchedule(unScheduleList, scheduledList);
    }


    private void calculateMinStartDate(TaskDto taskDto) {
        List<TaskModelDto> taskModelDtoList = this.baseMapper.getModelListByTaskdto(taskDto);
        Date startDate = new Date();
        for (TaskModelDto taskModelDto : taskModelDtoList) {
            if (taskModelDto.getActuallyEnddate() != null) {
                if (taskModelDto.getActuallyEnddate().getTime() > startDate.getTime()) {
                    startDate = taskModelDto.getActuallyEnddate();
                }
            } else if (taskModelDto.getDemandEnddate() != null) {
                if (taskModelDto.getDemandEnddate().getTime() > startDate.getTime()) {
                    startDate = taskModelDto.getDemandEnddate();
                }
            }
        }
        //排期按要求时间加1天,从第二天早上开始
        taskDto.setStartTime(getNextWorkTime(startDate));
        taskDto.setPlanStartdate(taskDto.getStartTime());
        taskDto.setPlanStarttime(DateUtil.parseDate("1970-01-01 09:00", "yyyy-MM-dd HH:mm"));
    }

    private Date getNextWorkTime(Date d) {
        d = DateUtils.addDays(d, 1);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String str = simpleDateFormat.format(d) + " 09:00";
        try {
            return (new SimpleDateFormat("yyyy-MM-dd HH:mm")).parse(str);
        } catch (ParseException ee) {
            return new Date();
        }
    }

    public void calculateSchedule(List<TaskDto> unScheduleList, List<TaskDto> scheduledList) {
        //未排期任务按所配资源分组
        Map<String, List<TaskDto>> unScheduleMap =
                unScheduleList.stream().collect(Collectors.groupingBy(TaskDto::getRsid));
        //已排期任务按资源分组
        Map<String, List<TaskDto>> scheduleMap =
                scheduledList.stream().collect(Collectors.groupingBy(TaskDto::getRsid));
        //开始进行排期
        for (String rsid : unScheduleMap.keySet()) {
            List<TaskDto> undoList = unScheduleMap.get(rsid);
            undoList.sort(new Comparator<TaskDto>() {
                @Override
                public int compare(TaskDto o1, TaskDto o2) {
                    if (o1.getStartTime() != null && o2.getStartTime() != null) {
                        if (o1.getStartTime().getTime() < o2.getStartTime().getTime()) {
                            return -1;
                        } else if (o1.getStartTime().getTime() > o2.getStartTime().getTime()) {
                            return 1;
                        } else if (o1.getPlanStarttime().getTime() < o2.getPlanStarttime().getTime()) {
                            return -1;
                        } else {
                            return 1;
                        }
                    } else {
                        return -1;
                    }
                }
            });
            List<TaskDto> dolist = scheduleMap.get(rsid);
            List<ScheduleLine> scheduleLineList = new ArrayList<>();
            //加上日历
            List<Calendar> calendarList = calendarService.findCalendarList(new Calendar());
            for (Calendar calendar : calendarList) {
                Date calendarEndate = DateUtils.addDays(calendar.getEndTime(), -1);
                String str1 = DateUtil.getDateFormat(calendarEndate, "yyyy-MM-dd");
                String str2 = "17:00";
                ScheduleLine scheduleLine = new ScheduleLine(mergeDateTime(calendar.getStartTime(), null),
                                                             DateUtil.parseDate(str1 + " " + str2, "yyyy-MM-dd HH:mm"));
                scheduleLineList.add(scheduleLine);
            }

            if (CollectionUtils.isNotEmpty(dolist)) {
                for (TaskDto doline : dolist) {
                    ScheduleLine scheduleLine = new ScheduleLine(mergeDateTime(doline.getPlanStartdate(),
                                                                               doline.getPlanStarttime()),
                                                                 mergeDateTime(doline.getPlanEnddate(),
                                                                               doline.getPlanEndtime()));
                    scheduleLineList.add(scheduleLine);
                }
            }

            for (TaskDto undo : undoList) {
                Date startDate = mergeDateTime(undo.getPlanStartdate(), undo.getPlanStarttime());
                BigDecimal testday = undo.getTestDay();
                Date endDate = addFloatDay(startDate, testday);
                Collections.sort(scheduleLineList);
                for (ScheduleLine scheduleLine : scheduleLineList) {
                     /*如果排期任务的结束时间小于已排序任务的开始时间，则可以排在此任务前面，否则按任务的结束时间作为待
                      排期任务的开始时间 */
                    if (endDate.getTime() < scheduleLine.getStartTime().getTime() && isModelFree(undo, startDate,
                                                                                                 endDate)) {
                        break;
                    } else if (startDate.getTime() < scheduleLine.getEndTime().getTime()) {
                        startDate = scheduleLine.getEndTime();
                        endDate = addFloatDay(startDate, testday);
                    }
                }
                //如果开始时间为17：00开始，则转换成第二天9：00
                String hhmm = DateUtil.getDateFormat(startDate, "HH:mm");
                if ("17:00".equals(hhmm)) {
                    startDate = DateUtils.addHours(startDate, 16);
                }

                undo.setStartTime(DateUtil.parseDate(DateUtil.getDateFormat(startDate, "yyyy-MM-dd"), "yyyy-MM-dd"));
                undo.setPlanStartdate(undo.getStartTime());
                undo.setPlanStarttime(DateUtil.parseDate(DateUtil.getDateFormat(startDate, "HH:mm"), "HH:mm"));

                undo.setEndTime(DateUtil.parseDate(DateUtil.getDateFormat(endDate, "yyyy-MM-dd"), "yyyy-MM-dd"));
                undo.setPlanEnddate(undo.getEndTime());
                undo.setPlanEndtime(DateUtil.parseDate(DateUtil.getDateFormat(endDate, "HH:mm"), "HH:mm"));
                Task task = baseMapper.selectById(undo.getTaskCode());
                task.setStatus(1);
                task.setPlanStartdate(undo.getPlanStartdate());
                task.setPlanStarttime(undo.getPlanStarttime());
                task.setPlanEnddate(undo.getPlanEnddate());
                task.setPlanEndtime(undo.getPlanEndtime());
                baseMapper.updateById(task);
                //将已排期任务加入列表中
                scheduleLineList.add(new ScheduleLine(startDate, endDate));
            }
        }
    }

    private Date addFloatDay(Date date, BigDecimal testday) {
        int day = testday.intValue();
        String starttime = DateUtil.getDateFormat(date, "HH:mm");
        //9：00开始加一天，变成当天晚上17：00
        if ("09:00".equals(starttime) && day > 1) {
            day = day - 1;
            testday = testday.subtract(BigDecimal.ONE);
            date = DateUtils.addHours(date, 8);
        }
        Date endDate = DateUtils.addDays(date, day);
        float floatday = testday.floatValue() - day;
        if (floatday > 0) {
            String worktime = DateUtil.getDateFormat(endDate, "HH:mm");
            if ("09:00".equals(worktime)) {
                endDate = DateUtils.addHours(endDate, 3);
            } else if ("12:00".equals(worktime)) {
                endDate = DateUtils.addHours(endDate, 5);
            } else if ("17:00".equals(worktime)) {
                //次日12：00
                endDate = DateUtils.addHours(endDate, 19);
            }
        }
        return endDate;
    }

    private boolean isModelFree(TaskDto taskDto, Date startDate, Date endDate) {
        boolean isfree = true;
        TaskShip taskShip = new TaskShip();
        taskShip.setTaskCode(taskDto.getTaskCode());
        List<TaskShip> taskShipList = this.taskShipService.findTaskShipList(taskShip);
        if (CollectionUtils.isNotEmpty(taskShipList)) {
            for (TaskShip ship : taskShipList) {
                TaskShip model = new TaskShip();
                model.setShipCode(ship.getShipCode());
                List<TaskShip> modelShipList = this.taskShipService.findTaskShipList(model);
                for (TaskShip obj : modelShipList) {
                    if (taskDto.getTaskCode().equals(obj.getTaskCode())) {
                        continue;
                    }
                    Task task = this.taskService.findTaskById(obj.getTaskCode());
                    if (task.getPlanStartdate() == null || task.getPlanEnddate() == null) {
                        continue;
                    }
                    if (!(endDate.getTime() < mergeDateTime(task.getPlanStartdate(), task.getPlanStarttime()).getTime()
                          || startDate.getTime() > mergeDateTime(task.getPlanEnddate(), task.getPlanEndtime()).getTime())) {
                        isfree = false;
                        break;
                    }

                }
            }
        }
        return isfree;
    }

    public static Date mergeDateTime(Date date, Date time) {
        String str1 = DateUtil.getDateFormat(date, "yyyy-MM-dd");
        String str2 = "09:00";
        if (time != null) {
            str2 = DateUtil.getDateFormat(time, "HH:mm");
        }
        return DateUtil.parseDate(str1 + " " + str2, "yyyy-MM-dd HH:mm");
    }


    @Override
    public List<TaskDto> findTaskList(TaskDto taskDto) {
        List<TaskDto> list = this.baseMapper.getSchedule(taskDto);
        for (TaskDto dto : list) {
            if (org.apache.commons.lang3.StringUtils.isNotBlank(dto.getFileinfo())) {
                dto.setFileList(JSON.parseArray(dto.getFileinfo()));
            }
        }
        list = list.stream().map(obj -> {
            WorkflowRecord workflowRecord = new WorkflowRecord();
            workflowRecord.setVoucherId("7");
            workflowRecord.setVoucherId(taskDto.getTaskCode());
            List<WorkflowRecord> workflowRecordList = this.workflowRecordService.findWorkflowRecordList(workflowRecord);
            List<TaskModelDto> taskModelDtoList = this.baseMapper.getModelListByTaskdto(obj);
            obj.setWorkflowArray(JSON.parseArray(JSON.toJSONString(workflowRecordList)));
            obj.setTaskModelArray(JSON.parseArray(JSON.toJSONString(taskModelDtoList)));
            return obj;
        }).collect(Collectors.toList());
        return list;
    }

    @Override
    public List<TaskDto> getAssembledTask(TaskDto taskDto) {
        List<TaskDto> list = findTaskList(taskDto);
        //已排期
        list = list.stream().filter(obj -> obj.getPlanStartdate() != null && obj.getPlanEnddate() != null && obj.getRsid() != null).collect(Collectors.toList());
        for (TaskDto obj : list) {
            if (5 == obj.getStatus()) {
                obj.setRateColor("86D46A");
            } else if (6 == obj.getStatus()) {
                obj.setRateColor("9D9D9D");
                obj.setIsDrag(false);
            } else if (7 == obj.getStatus()) {
                obj.setRateColor("C8626E");
                obj.setIsDrag(false);
            } else if (isCompleteModel(obj)) {
                obj.setIsPossibleTest(true);
                obj.setRateColor("67D1FF");
            } else {
                obj.setIsPossibleTest(false);
                obj.setRateColor("E9EE00");
            }
            obj.setTaskColor(obj.getRateColor());
        }
        return list;
    }

    public boolean isCompleteModel(TaskDto taskDto) {
        List<TaskModelDto> taskModelDtoList = this.baseMapper.getModelListByTaskdto(taskDto);
        boolean result = true;
        for (TaskModelDto taskModelDto : taskModelDtoList) {
            if (taskModelDto.getActuallyEnddate() == null) {
                result = false;
                break;
            }
        }
        return result;
    }

    @Override
    @Transactional
    public void commit(TaskDto taskDto) {
        WorkflowRecord workflowRecord = new WorkflowRecord();
        workflowRecord.setVoucherId(taskDto.getTaskCode());
        workflowRecord.setVoucherType("7");
        workflowRecord.setStatus(2);
        workflowRecord.setRemark("提交");
        workflowRecord.setDeletedFlg("0");
        workflowRecordService.save(workflowRecord);
        Task task = this.baseMapper.selectById(taskDto.getTaskCode());
        task.setPlanStartdate(taskDto.getPlanStartdate());
        task.setPlanStarttime(taskDto.getPlanStarttime());
        task.setPlanEnddate(taskDto.getPlanEnddate());
        task.setPlanEndtime(taskDto.getPlanEndtime());
        task.setTestDay(taskDto.getTestDay());
        task.setRemark(taskDto.getRemark());
        task.setStatus(2);
        baseMapper.updateById(task);
        //如果是资源管理员，则直接审核
        String userid = getCurrentUser().getUserId();
        if (userid.equals(taskDto.getRsDirector())) {
            workflowRecord = new WorkflowRecord();
            workflowRecord.setDeletedFlg("0");
            workflowRecord.setVoucherType("7");
            workflowRecord.setVoucherId(taskDto.getTaskCode());
            workflowRecord.setStatus(4);
            workflowRecordService.save(workflowRecord);
            task.setStatus(4);
            this.baseMapper.updateById(task);
        }
        if (!userid.equals(taskDto.getRsDirector())) {
            try {
                //审核不通过通知置为已读
                Notice dealNotice = new Notice();
                dealNotice.setBizId(taskDto.getTaskCode());
                dealNotice.setNoticeTitle("排期审核结果（不通过）");
                noticeService.dealDone(dealNotice);

                //待办通知
                String content = "(" + task.getProjectCode() + "项目" + taskDto.getTaskCode() + ")排期更新待审核";
                Notice notice = new Notice();
                notice.setNoticeType(2);
                notice.setPendingType("排期审核通知");
                notice.setNoticeTitle("排期审核通知");
                notice.setNoticeContent(content);
                notice.setReceiveUserId(taskDto.getRsDirector());
                notice.setUrl("/schedule");
                notice.setBizId(task.getTaskCode());
                noticeService.createNotice(notice);
            } catch (Exception e) {
                log.error("saveAuditSypqProject: notice error:", e);
            }
        }
    }

    /**
     * 修改
     *
     * @param task task
     * @author ganjun
     * @date 2024-11-18 10:06:38
     */
    @Override
    @Transactional
    public void batchCommit(TaskDto taskDto, Boolean isAdmin) {
        //只有排期任务才向审批流表中插入记录
        String currentUser = getCurrentUser().getUserId();
        List<TaskDto> list = this.baseMapper.getSchedule(taskDto);
        //项目经理只提交自己的项目
        list = list.stream().filter(obj ->
                                            (obj.getManagerids().contains(currentUser) || isAdmin) && obj.getStartTime() != null && obj.getEndTime() != null)
                   .collect(Collectors.toList());
        List<WorkflowRecord> workflowRecordList = new ArrayList<>();
        for (TaskDto obj : list) {
            WorkflowRecord workflowRecord = new WorkflowRecord();
            workflowRecord.setVoucherId(obj.getTaskCode());
            workflowRecord.setVoucherType("7");
            workflowRecord.setStatus(2);
            workflowRecord.setRemark("提交");
            workflowRecord.setDeletedFlg("0");
            workflowRecordList.add(workflowRecord);
            Task task = this.baseMapper.selectById(obj.getTaskCode());
            task.setStatus(2);
            baseMapper.updateById(task);
            //待办通知
            try {
                //审核不通过通知置为已读
                Notice dealNotice = new Notice();
                dealNotice.setBizId(taskDto.getTaskCode());
                dealNotice.setNoticeTitle("排期审核结果（不通过）");
                noticeService.dealDone(dealNotice);

                //待办通知
                String rsId = task.getRsid();
                Resource resource = this.resourceService.getById(rsId);
                if (resource != null) {
                    String content = "(" + task.getProjectCode() + "项目" + task.getTaskCode() + ")排期更新待审核";
                    Notice notice = new Notice();
                    notice.setNoticeType(2);
                    notice.setPendingType("排期审核通知");
                    notice.setNoticeTitle("排期审核通知");
                    notice.setNoticeContent(content);
                    notice.setReceiveUserId(resource.getRsDirector());
                    notice.setReceiveRealName(resource.getRsDirectorName());
                    notice.setUrl("/schedule");
                    notice.setBizId(task.getTaskCode());
                    noticeService.createNotice(notice);
                }

            } catch (Exception e) {
                log.error("saveAuditSypqProject: notice error:", e);
            }
        }
        workflowRecordService.saveBatch(workflowRecordList);
    }

    public void updateSchedule(TaskDto taskDto) throws Exception {
        //检查资源是否被占用
        Task task = this.baseMapper.selectById(taskDto.getTaskCode());
        taskDto.setRsid(task.getRsid());
        //修改工时。计划开始时间和结束时间
        String checkinfo = checkTask(taskDto);
        if (checkinfo.length() > 0) {
            throw new Exception(checkinfo);
        }

        Date origPlanStartdate = task.getPlanStartdate();
        task.setPlanStartdate(taskDto.getPlanStartdate());
        task.setPlanStarttime(taskDto.getPlanStarttime());
        task.setPlanEnddate(taskDto.getPlanEnddate());
        task.setPlanEndtime(taskDto.getPlanEndtime());
        if (taskDto.getTestDay() != null) {
            task.setTestDay(taskDto.getTestDay());
        }
        this.baseMapper.updateById(task);

        try {
            //待办通知
            String content =
                    "{" + task.getProjectCode() + "项目" + taskDto.getTaskCode() + "任务}原计划" + DateUtil.getDateFormat(origPlanStartdate, "yyyy-MM-dd HH:mm") + "开始已改变，更新的计划开始时间为" + DateUtil.getDateFormat(taskDto.getPlanStartdate(), "yyyy-MM-dd HH:mm") + "，计划完成时间为" + DateUtil.getDateFormat(taskDto.getPlanEnddate(), "yyyy-MM-dd HH:mm") + "，请及时关注";
            Notice notice = new Notice();
            notice.setNoticeType(1);
            notice.setPendingType("排期变更");
            notice.setNoticeTitle("排期变更");
            notice.setNoticeContent(content);

            String loginName = task.getCreatedBy();
            if (StringUtils.isNotEmpty(loginName)) {
                User user = userService.findByName(loginName);
                if (user != null) {
                    notice.setReceiveUserId(user.getUserId());
                    notice.setReceiveRealName(user.getUname());
                }
            }
            notice.setUrl("");
            noticeService.createNotice(notice);
        } catch (Exception e) {
            log.error("saveAuditSypqProject: notice error:", e);
        }
    }

    @Override
    public void deleteSchedule(String taskcode, int status) {
        TaskDto taskDto = new TaskDto();
        taskDto.setStatus(status);
        taskDto.setTaskCode(taskcode);
        this.baseMapper.deleteSchedule(taskDto);

        try {
            //待办通知
            Task task = taskService.getById(taskcode);
            String content = "(" + task.getProjectCode() + "项目" + taskDto.getTaskCode() + ")排期取消，请及时关注，如需继续可以重新排期提交";
            Notice notice = new Notice();
            notice.setNoticeType(1);
            notice.setPendingType("排期变更");
            notice.setNoticeTitle("修改排期（计划取消）");
            notice.setNoticeContent(content);

            if (task != null) {
                String loginName = task.getCreatedBy();
                if (StringUtils.isNotEmpty(loginName)) {
                    User user = userService.findByName(loginName);
                    if (user != null) {
                        notice.setReceiveUserId(user.getUserId());
                        notice.setReceiveRealName(user.getUname());
                    }
                }
            }
            notice.setUrl("/schedule");
            noticeService.createNotice(notice);
        } catch (Exception e) {
            log.error("saveAuditSypqProject: notice error:", e);
        }
    }

    public Date getMaxPlanEnddate() {
        return this.baseMapper.getMaxPlanEnddate();
    }

    public List<TaskDto> findExcelList(TaskDto taskDto) {
        List<TaskDto> list = this.baseMapper.getTaskDetail(taskDto, "");
        //筛选我的排期
        String currentUser = getCurrentUser().getUserId();
        if ("1".equals(taskDto.getMySchedule())) {
            list = list.stream().filter(obj -> {
                return Arrays.asList(obj.getManagerids().split(",")).contains(currentUser) ||
                       currentUser.equals(obj.getAuditorid());
            }).collect(Collectors.toList());
        }
        //已排期
        List<TaskDto> scheduledList =
                list.stream().filter(obj -> obj.getPlanStartdate() != null && obj.getPlanEnddate() != null && obj.getRsid() != null).collect(Collectors.toList());
        return scheduledList;
    }

    @Override
    public void batchAudit(TaskDto taskDto, Boolean isAdmin) throws Exception {
        String currentUser = getCurrentUser().getUserId();
        if (isAdmin) {
            currentUser = "";
        }
        List<TaskDto> list = this.baseMapper.getTaskDetail(taskDto, currentUser);
        final String userid = currentUser;
        list = list.stream().filter(obj -> userid.equals(obj.getRsDirector()) || isAdmin).collect(Collectors.toList());
        List<WorkflowRecord> workflowRecordList = new ArrayList<>();
        for (TaskDto obj : list) {
            WorkflowRecord workflowRecord = new WorkflowRecord();
            workflowRecord.setVoucherId(obj.getTaskCode());
            workflowRecord.setDeletedFlg("0");
            workflowRecord.setVoucherType("7");
            workflowRecord.setStatus(4);
            workflowRecordList.add(workflowRecord);
            Task task = this.baseMapper.selectById(obj.getTaskCode());
            task.setStatus(4);
            this.baseMapper.updateById(task);
        }
        this.workflowRecordService.saveBatch(workflowRecordList);
    }


    @Override
    @Transactional
    public boolean saveAudit(WorkflowRecord workflowRecord) {
        String taskcode = workflowRecord.getVoucherId();
        Task task = this.baseMapper.selectById(taskcode);
        task.setStatus(workflowRecord.getStatus());
        this.baseMapper.updateById(task);
        workflowRecord.setVoucherType("7");
        workflowRecord.setDeletedFlg("0");
        boolean res = workflowRecordService.createWorkflowRecord(workflowRecord);
        if (res) {
            try {
                //待办通知
                Notice notice = new Notice();
                String content = "";
                if (4 == workflowRecord.getStatus()) {
                    notice.setNoticeType(1);
                    notice.setNoticeTitle("排期审核结果(通过)");
                    content =
                            "(" + task.getProjectCode() + ")项目" + task.getTaskCode() + "任务)审核已通过，计划开始时间为" + task.getPlanStartdate() + " " + task.getPlanStarttime() + "，计划完成时间为" + task.getPlanEnddate() + " " + task.getPlanEndtime() + "，请及时关注";
                } else if (3 == workflowRecord.getStatus()) {
                    //待处理通知置为已读
                    Notice dealNotice = new Notice();
                    dealNotice.setBizId(taskcode);
                    dealNotice.setNoticeTitle("排期审核通知");
                    noticeService.dealDone(dealNotice);
                    deleteSchedule(taskcode, 3);
                    //不通过通知
                    notice.setNoticeType(2);
                    notice.setNoticeTitle("排期审核结果（不通过）");
                    notice.setUrl("/schedule");
                    notice.setBizId(task.getTaskCode());
                    content =
                            "(" + task.getProjectCode() + ")项目" + task.getTaskCode() + ")任务审核未通过(原因：" + workflowRecord.getRemark() + ")，请及时修改";
                }
                notice.setPendingType("排期审核结果");
                notice.setNoticeContent(content);
                String loginName = task.getCreatedBy();
                if (StringUtils.isNotEmpty(loginName)) {
                    User user = userService.findByName(loginName);
                    if (user != null) {
                        notice.setReceiveUserId(user.getUserId());
                        notice.setReceiveRealName(user.getUname());
                    }
                }
                noticeService.createNotice(notice);

            } catch (Exception e) {
                log.error("ScheduleServiceImpl saveAudit: notice error:", e);
            }
        }
        return res;
    }

    public List<TaskTestDto> getTaskTestList(String rscode) {
        TaskDto taskDto = new TaskDto();
        taskDto.setRsCode(rscode);
        SimpleDateFormat sb = new SimpleDateFormat("yyyy-MM-dd EEEE");
        List<TaskTestDto> list = this.baseMapper.getTaskTestList(taskDto);
        list.forEach(obj -> {
            if (obj.getPlanStartDate() != null) {
                obj.setPlanStartStr(sb.format(obj.getPlanStartDate()));
            }
        });
        return list;
    }

    public String checkTask(TaskDto taskDto) {
        StringBuffer sb = new StringBuffer();
        Task task = this.baseMapper.selectById(taskDto.getTaskCode());
        TaskDto param = new TaskDto();
        param.setRsid(task.getRsid());
        List<TaskDto> taskDtoList = getAssembledTask(param);
        Date starttime = mergeDateTime(taskDto.getPlanStartdate(), taskDto.getPlanStarttime());
        Date endtime = mergeDateTime(taskDto.getPlanEnddate(), taskDto.getPlanEndtime());
        for (TaskDto obj : taskDtoList) {
            Date assemStart = mergeDateTime(obj.getPlanStartdate(), obj.getStartTime());
            Date assemEnd = mergeDateTime(obj.getPlanEnddate(), obj.getPlanEndtime());
            if (endtime.getTime() <= assemStart.getTime() || starttime.getTime() >= assemEnd.getTime() || obj.getTaskCode().equals(taskDto.getTaskCode())) {
                continue;
            } else {
                sb.append("资源已被任务" + obj.getTaskCode() + "占用,排期失败!");
                break;
            }
        }
        //检查日历停用情况
        List<Calendar> calendarList = calendarService.findCalendarList(new Calendar());

        for (Calendar calendar : calendarList) {
            Date calendarEndate = DateUtils.addDays(calendar.getEndTime(), -1);
            String str1 = DateUtil.getDateFormat(calendarEndate, "yyyy-MM-dd");
            String str2 = "17:00";
            ScheduleLine scheduleLine = new ScheduleLine(mergeDateTime(calendar.getStartTime(), null),
                                                         DateUtil.parseDate(str1 + " " + str2, "yyyy-MM-dd HH:mm"));
            if (endtime.getTime() <= scheduleLine.getStartTime().getTime() || starttime.getTime() >= scheduleLine.getEndTime().getTime()) {
                continue;
            } else {
                sb.append("资源已被日历锁定,排期失败!");
                break;
            }
        }


        Date minPlanDate = getMinPlanDate(taskDto.getTaskCode());
        if (DateUtil.getDateFormat(minPlanDate, "yyyy-MM-dd").
                    compareTo(DateUtil.getDateFormat(taskDto.getPlanStartdate(), "yyyy-MM-dd")) > 0) {
            sb.append("计划开始时间必须晚于模型中的最晚要求完成时间/实际完成时间" + DateUtil.getDateFormat(minPlanDate, "yyyy-MM-dd HH:mm"));
        }
        return sb.toString();
    }

    public Date getMinPlanDate(String taskcode) {
        TaskDto taskDto = new TaskDto();
        taskDto.setTaskCode(taskcode);
        calculateMinStartDate(taskDto);
        return taskDto.getStartTime();
    }


}
